package com.xgxd.commons.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;

/**
 * service日志监控
 *
 * @author YanLee
 * com.xgxd.aop
 * @date 2017/9/22
 */
@Aspect
@Component
public class ServiceLogAspect {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private static final ThreadLocal<Long> startTimeThreadLocal =  new NamedThreadLocal<Long>("ThreadLocal StartTime");

    @Pointcut("execution(public * com.xgxd.modules.domain..*.*(..))")
    public void serviceLog(){}

    @Before("serviceLog()")
    public void doBefore(JoinPoint joinPoint){
//        if(logger.isDebugEnabled()){
            startTimeThreadLocal.set(System.currentTimeMillis());
            Signature signature = joinPoint.getSignature();
            StringBuilder msg = new StringBuilder();
            msg.append("start "+signature.getDeclaringTypeName()+"."+signature.getName()+"  args=[");
            for(Object arg: joinPoint.getArgs()){
                //屏蔽字节流打印，如果对象中有字节流，请重写toString()方法时回避
                if(arg instanceof byte[]){
                    byte[] temp = (byte[]) arg;
                    msg.append("stream.length="+temp.length+", ");
                }else{
                    msg.append(arg+", ");
                }
            }
//            if(logger.isDebugEnabled()){
                logger.info(msg.substring(0, msg.length()-1)+"]");
//            }
//        }
    }

    @AfterReturning(returning = "ret", pointcut = "serviceLog()")
    public void afterReturns(JoinPoint joinPoint, Object ret){
        // 保存日志
//        LogUtils.saveLog( handler, ex, null);
        // 打印JVM信息。
//        if (logger.isDebugEnabled()){
            long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量（开始时间）
            long endTime = System.currentTimeMillis(); 	//2、结束时间
            logger.info("计时结束：{}  耗时：{} 最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",
                    new SimpleDateFormat("hh:mm:ss.SSS").format(endTime),
                    Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
                    (Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
            //删除线程变量中的数据，防止内存泄漏
            startTimeThreadLocal.remove();
//        }
    }

}
